package RockPaperScissors.GameFlow
{
    import RockPaperScissors.ProcessorStep;
    import RockPaperScissors.Utilities;
    
    import com.adobe.serialization.json.*;
    
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.http.HTTPService;
    
    public dynamic class PlayRound extends ProcessorStep
    {
        var results = {"contestant1":null, "contestant2":null};
        var contestant1_result;
        var contestant2_result;
        
        
        public function PlayRound(onComplete:Function=null, onFail:Function=null)
        {
            super(onComplete, onFail);
            this.setupProcessorStep(onComplete, onFail);
        }
        
        public override function Process(data)
        {
            var service:HTTPService = new HTTPService();
            
            var contestant1_uri = data["contestant1"]["uri"] + "/play";
            service.url = contestant1_uri;
            service.addEventListener(FaultEvent.FAULT, Utilities.createCallBack(onContestant1Fail, {"contestant":"contestant1", "data":data, "context":this}));
            service.addEventListener(ResultEvent.RESULT, 
                Utilities.createCallBack(this.onComplete, {"contestant":"contestant1", "data":data, "context":this}));
            service.send();
            
            service = new HTTPService();
            var contestant2_uri = data["contestant2"]["uri"] + "/play";
            service.url = contestant2_uri;
            service.addEventListener(FaultEvent.FAULT, Utilities.createCallBack(onContestant2Fail, {"contestant":"contestant1", "data":data, "context":this}));
            service.addEventListener(ResultEvent.RESULT, 
                Utilities.createCallBack(this.onComplete, {"contestant":"contestant2", "data":data, "context":this}));
            service.send();
            
        }
        
        public function onContestant1Fail(event:FaultEvent, data:*)
        {
            var error = event.message;
            var result = "exception";
            data["data"]["contestant1"]["lost_by_exception"] = true;
            this.ProcessingError(data["data"]);
        }
        
        public function onContestant2Fail(event:FaultEvent, data:*)
        {
            var error = event.message;
            var result = "exception";
            data["data"]["contestant2"]["lost_by_exception"] = true;
            this.ProcessingError(data["data"]);
            //processResults(result, data);
        }
        
        public function processResults(result:String, data)
        {
            var contestant_name:String = data["contestant"];
            results[contestant_name] = result;
            
            //Then both contestants have competed.
            if(results["contestant1"] != null && results["contestant2"] != null)
            {
                //Place results in the results history.
                //Tell your parent you're complete!
                var winner = decide_winner(
                        {
                            "contestant1":results["contestant1"],
                            "contestant2":results["contestant2"]
                        },
                        data["data"]);
                
                if(winner == "contestant1")
                {
                    //We also add the number of draws we've accumulated.
                    data["data"]["contestant1"]["wins"] = data["data"]["contestant1"]["wins"] + 1 + data["data"]["draw_counter"];
                    data["data"]["contestant2"]["losses"] = data["data"]["contestant2"]["losses"] + 1;
                    
                    //here we reset our draw counter.
                    data["data"]["draw_counter"] = 0;
                }
                if(winner == "contestant2")
                {
                    //We also add the number of draws we've accumulated.
                    data["data"]["contestant2"]["wins"] = data["data"]["contestant2"]["wins"] + 1 + data["data"]["draw_counter"];
                    data["data"]["contestant1"]["losses"] = data["data"]["contestant1"]["losses"] + 1;
                    
                    //here we reset our draw counter.
                    data["data"]["draw_counter"] = 0;
                }
                if(winner == "draw")
                {
                    data["data"]["contestant2"]["draws"] = data["data"]["contestant2"]["draws"] + 1;
                    data["data"]["contestant1"]["draws"] = data["data"]["contestant1"]["draws"] + 1;
                    data["data"]["draw_counter"] ++;
                }
                
                data["data"]["rounds"].push(
                {
                    "contestant1":results["contestant1"],
                    "contestant2":results["contestant2"],
                    "winner": winner
                });
                
                this.ProcessingComplete(data["data"]);
            }
        }
        
        public function onComplete(event:ResultEvent, data)
        {
            var result = event.result;
            processResults(result, data);
        }
        
        
        public function decide_winner(round_data, data)
        {
            var game_rules = 
            {
                "rock" : 
                {
                    "paper":"lose",
                    "scissors":"win",
                    "rock":"draw",
                    "exception":"win"
                },
                "paper" : 
                {
                    "paper":"draw",
                    "scissors":"lose",
                    "rock":"win",
                    "exception":"win"
                },
                "scissors" : 
                {
                    "paper":"win",
                    "scissors":"draw",
                    "rock":"lose",
                    "exception":"win"
                },  
                "exception" :
                {
                    "paper":"lose",
                    "scissors":"lose",
                    "rock":"lose",
                    "exception":"draw"
                }
            }
        //Begin Dynamite rules
            if(round_data["contestant1"] == "dynamite" || round_data["contestant2"] == "dynamite")
            {
                var a = "stop here";
            }
            //if contestant1 used dynamite, contestant2 didn't, AND contestant1 HAS dynamite
            //then contestant1 wins and they need to lose some dynamite.
            if(round_data["contestant1"] == "dynamite" && 
                round_data["contestant2"] != "dynamite" &&
                data["contestant1"]["dynamite_count"] > 0)
            {
                data["contestant1"]["dynamite_count"] --;
                return "contestant1";
            }
            
            //if contestant2 used dynamite, contestant1 didn't, AND contestant2 HAS dynamite
            //then contestant2 wins and they need to lose some dynamite.
            if(round_data["contestant2"] == "dynamite" && 
                round_data["contestant1"] != "dynamite" &&
                data["contestant2"]["dynamite_count"] > 0)
            {
                data["contestant2"]["dynamite_count"] --;
                return "contestant2";
            }
            
            //if both contestants used dynamite
                //if contestant1 doesn't have dynamite but contestant2 does, then contestant2 wins.
                //if contestant2 doesn't have dynamite but contestant1 does, then contestant1 wins.
                //if neither have dynamite then it is a draw.
            if(round_data["contestant1"] == "dynamite" && 
                round_data["contestant2"] == "dynamite")
            {
                if(data["contestant1"]["dynamite_count"] > 0 &&
                    data["contestant2"]["dynamite_count"] <= 0)
                {
                    data["contestant1"]["dynamite_count"] --;
                    return "contestant1";
                }
                if(data["contestant2"]["dynamite_count"] > 0 &&
                    data["contestant1"]["dynamite_count"] <= 0)
                {
                    data["contestant2"]["dynamite_count"] --;
                    return "contestant2";
                }
                if(data["contestant2"]["dynamite_count"] > 0 &&
                    data["contestant1"]["dynamite_count"] > 0)
                {
                    data["contestant1"]["dynamite_count"] --;
                    data["contestant2"]["dynamite_count"] --;
                    return "draw";
                }
                
                //Bug fix: it should be a draw if both players don't have
                //dynamite and both call it.
                if(data["contestant2"]["dynamite_count"] <= 0 &&
                    data["contestant1"]["dynamite_count"] <= 0)
                {
                    return "draw";
                }
            }
            if(round_data["contestant1"] == "dynamite" && 
                data["contestant1"]["dynamite_count"] == 0 &&
                round_data["contestant2"] != "dynamite")
            {
                return "contestant2";
            }
            
            if(round_data["contestant2"] == "dynamite" && 
                data["contestant2"]["dynamite_count"] == 0 &&
                round_data["contestant1"] != "dynamite")
            {
                return "contestant1";
            }
       //End Dynamite rules    

            if(game_rules[round_data["contestant1"]][round_data["contestant2"]] == "win")
            {
                return "contestant1";
            }
            if(game_rules[round_data["contestant1"]][round_data["contestant2"]] == "lose")
            {
                return "contestant2";
            }
            
            return "draw";
  
            
        }
    }
}